package com.zhongwang.mms.module.purchase.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.zhongwang.mms.common.JsonResult;
import com.zhongwang.mms.gen.entity.PInventory;
import com.zhongwang.mms.gen.entity.TWarehouseInfo;
import com.zhongwang.mms.gen.entity.User;
import com.zhongwang.mms.module.basic.dao.TWarehouseInfoDao;
import com.zhongwang.mms.module.half.dao.PAllocationRecordDao;
import com.zhongwang.mms.module.purchase.dao.PurChangeDao;
import com.zhongwang.mms.module.purchase.dao.PurPInventoryDao;
import com.zhongwang.mms.module.purchase.dao.PurWarQueryDao;
import com.zhongwang.mms.module.purchase.model.*;
import com.zhongwang.mms.module.purchase.model.check.PCheckDetailExcelModel;
import com.zhongwang.mms.module.purchase.model.check.PCheckPlanModel;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.module.system.user.UserDao;
import com.zhongwang.mms.util.ExportExcelUtils;
import com.zhongwang.mms.util.FileUtils;
import com.zhongwang.mms.util.ShiroUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.math3.geometry.spherical.oned.ArcsSet;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName： AllocationManageService
 * @Description： 出入库查询业务逻辑层
 * @Author： China.zh
 * @Date： 2020/4/8 10:36
 * @Version： V1.0
 **/
@Log4j2
@Service
public class PurWarQueryService {
    @Autowired
    private PurWarQueryDao purWarQueryDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private PAllocationRecordDao pAllocationRecordDao;
    @Autowired
    private PurPInventoryDao purPInventoryDao;
    @Autowired
    private PurChangeDao purChangeDao;
    @Autowired
    private PurWarOutManageService purWarOutManageService;
    @Autowired
    private LogService logService;
    @Autowired
    private TWarehouseInfoDao tWarehouseInfoDao;
    @Value("${user.upload.path}")
    private String uploadPath;
    @Value("${spring.profiles.active}")
    private String active;

    /**
     * findPurWarList
     * 加载出入库列表以及综合查询
     *
     * @param param 查询条件
     * @return
     */
    public List<PurWarQueryModel> findPurWarList(PurWarQueryModel param) {
        if (param.getPEndDate() != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(param.getPEndDate());
            cal.add(Calendar.DAY_OF_YEAR, 1);
            param.setPEndDate(cal.getTime());
        }
        return purWarQueryDao.selectByParam(param);
    }

    /**
     * 出入库查询 查看明细
     *
     * @param param
     * @return
     */
    public PurOrderForQueryResultModel findOrderInfoByOdrId(PurWarQueryModel param) {
        PurOrderForQueryResultModel purOrderModel = new PurOrderForQueryResultModel();
        POrderQueryPrintModel pOrder = purWarQueryDao.getOrderByOdrId(param.getOdrId());
        pOrder.setOdrMakePerson(userDao.findUserById(pOrder.getOdrMakePersonId()).getName());
        List<POrderDetail> pOrderDetailList = null;
        if (pOrder.getOdrType().intValue() == 1) {
            pOrderDetailList = purWarQueryDao.getOrderInByOdrId(param.getOdrId());
        } else {
            pOrderDetailList = purWarQueryDao.getOrderOutByOdrId(param.getOdrId());
        }
        if (pOrder.getOdrType().intValue() == 2) {
            for (POrderDetail pOrderDetail : pOrderDetailList) {
                PInventory pInventory = purPInventoryDao.getPInventoryByPK(pOrderDetail.getOdaOutItyId());
                if (pInventory.getItyChangeFlag() != null && pInventory.getItyChangeFlag() != 2) {
                    purOrderModel.setIsChangeFlag(pInventory.getItyChangeFlag());
                    //1.溯源：找回此物料最原始的串料信息，即始祖库存信息，找寻方式，
                    //通过此库存ID在串料执后的信息中获取上一级，以此类推。
                    PInventoryModel pInventoryModel = findAncestorChangeData(pInventory.getItyId());
                    //2.累计计算剩余库存量：使始祖库存信息的原始入库数据量，计算此串料过程中所有库存中出库的数据。
                    PInventory getNumModel = new PInventory();
                    getNumModel.setItyNum(pInventoryModel.getItyNum());
                    getNumModel.setItyId(pInventoryModel.getItyId());
                    pOrderDetail.setOdaNumSource(pOrderDetail.getOdaAtThatTimeAncestorsNum());
                    pOrderDetail.setOdaProCodeSource(pInventoryModel.getItyProCode());
                    pOrderDetail.setOdaProNameSource(pInventoryModel.getItyProName());
                }
            }
        }
        if (purOrderModel.getIsChangeFlag() == null) {
            purOrderModel.setIsChangeFlag(0);
        }
        purOrderModel.setFormData(pOrder);
        for (int i = 0; i <pOrderDetailList.size() ; i++) {
            if (pOrderDetailList.get(i).getOdaBookkeepingDate() !=null&&pOrderDetailList.get(i).getOdaBookkeepingDate().length()>10)
            pOrderDetailList.get(i).setOdaBookkeepingDate(pOrderDetailList.get(i).getOdaBookkeepingDate().substring(0,10));
        }
        purOrderModel.setInsertData(pOrderDetailList);
        //如果是调拨单则查询调拨单内容
        if (pOrder.getOdrReqFlag().equals(1)) {
            //根据主单ID获取调拨记录
            purOrderModel.setPAllocationRecordList(pAllocationRecordDao.getAllocationRecordListByOdrId(pOrder.getOdrId()));
        }
        return purOrderModel;
    }

    /**
     * @FunctionName: getChangeOrderInvCount
     * @Description: 获取已执行的和已出库库存信息，获取其数量进行相加
     * @DesignIdea: 默认认为只串一次料
     * @Author: 徐一贺
     * @CreateDate: 2020/6/29 13:32
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Throw:
     * @Version: v 1.0.0
     */
    private Double getChangeOrderInvCount(Integer ceoUseItyId) {
        Double result = 0d;
        //获取根节点列表
        List<PChangeOrderModel> pChangeOrderModelList = purChangeDao.findPChangeOrderListByCeoNeedItyId(ceoUseItyId);
        for (PChangeOrderModel pChangeOrderModel : pChangeOrderModelList) {
            PInventoryModel pInvModel = purPInventoryDao.getInventoryByPrimaryKey(pChangeOrderModel.getCeoNeedItyId());
            result += pInvModel.getItyNum();
        }
        return result;
    }

    private Double getChangeUseOrderInvCount(Integer ceoUseItyId) {
        Double result = 0d;
        //获取根节点列表
        List<PChangeOrderModel> pChangeOrderModelList = purChangeDao.findPChangeOrderListByCeoUseItyId(ceoUseItyId);
        for (PChangeOrderModel pChangeOrderModel : pChangeOrderModelList) {
            PInventoryModel pInvModel = purPInventoryDao.getInventoryByPrimaryKey(pChangeOrderModel.getCeoUseItyId());
            result += pInvModel.getItyNum();
        }
        return result;
    }

    /**
     * @FunctionName: findAncestorChangeData
     * @Description: 根据子孙ID 获取串料历史中始祖的信息，并获取始祖信息时的库存数量
     * @DesignIdea: 使用递归获取始祖库存ID，并返回当前信息的始祖库存信息
     * @Author: 徐一贺
     * @CreateDate: 2020/6/29 9:47
     * @Phone: 18241927380
     * @Param: [ceoNeedItyId] 需求库存ID
     * @Return: [PInventoryModel]检索到的库存信息
     * @Throw:
     * @Version: v 1.0.0
     */
    private PInventoryModel findAncestorChangeData(Integer ceoNeedItyId) {
        PInventoryModel result = purPInventoryDao.getInventoryByPrimaryKey(ceoNeedItyId);
        PChangeOrderModel currentModel = new PChangeOrderModel();
        currentModel.setCeoNeedItyId(ceoNeedItyId);
        while (true) {
            if (currentModel != null) {
                currentModel = purChangeDao.getChangeCountByCeoNeedItyId(currentModel.getCeoNeedItyId());
            }
            if (currentModel != null) {
                result = purPInventoryDao.getInventoryByPrimaryKey(currentModel.getCeoUseItyId());
                currentModel = purChangeDao.getChangeCountByCeoNeedItyId(currentModel.getCeoUseItyId());
            } else {
                break;
            }
        }
        return result;
    }

    /**
     * 列表 导出
     *
     * @param param 查询条件
     * @return list
     */
    public void exportExcel(HttpServletResponse response, PurWarQueryModel param) {
        if (param.getPEndDate() != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(param.getPEndDate());
            cal.add(Calendar.DAY_OF_YEAR, 1);
            param.setPEndDate(cal.getTime());
        }
        //获取当前用户
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        //存储/读取Excel的文件夹的路径 mms文件夹下/用户账户/
        String path = uploadPath + user.getAccount() + "/";
        Subject userSubject = ShiroUtils.getSubject();
        try {
            //1.创建临时内存表名
            String tempTableName = "##" + user.getAccount() + (UUID.randomUUID().toString().replace("-", ""));
            param.setTempTableName(tempTableName);
            //2.查询出数据导入到临时表
            if (userSubject.isPermitted("purwar:amount:view")) {
                purWarQueryDao.createWarQueryTempTableByParam(param);
            } else {
                purWarQueryDao.createWarQueryTempTableByParamAndNoAmount(param);
            }
            //3.导出Excel
            boolean result = ExportExcelUtils.Export(path, "外购件库出入库综合查询.xlsx", tempTableName, response, active);
        } catch (Exception e) {
            log.debug(e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 创建要导出的Excel
     *
     * @param param 查询条件
     * @return list
     */
    public JsonResult exportExcel(PurWarQueryModel param) {
        // 记录开始时间（纳秒）
        long startTime = System.nanoTime();
        Date startTimeDate = new Date();
        StringBuilder searchCondition = new StringBuilder();
        if(!param.getOdrCode().isEmpty()){
            searchCondition.append("，单据编号：").append(param.getOdrCode());
        }
        if(!param.getOdaProCode().isEmpty()){
            searchCondition.append("，项目编号：").append(param.getOdaProCode());
        }
        if(!param.getOdaProName().isEmpty()){
            searchCondition.append("，项目名称：").append(param.getOdaProName());
        }
        if(!param.getOdaSapCode().isEmpty()){
            searchCondition.append("，SAP物料编码：").append(param.getOdaSapCode());
        }
        if(!param.getOdaMatDesc().isEmpty()){
            searchCondition.append("，物料描述：").append(param.getOdaMatDesc());
        }
        if(!param.getOdaTrackCode().isEmpty()){
            searchCondition.append("，跟踪号：").append(param.getOdaTrackCode());
        }
        if(!param.getName().isEmpty()){
            searchCondition.append("，制单人：").append(param.getName());
        }
        if(!param.getOdrTakePerson().isEmpty()){
            searchCondition.append("，领料人：").append(param.getOdrTakePerson());
        }
        if(!param.getOdaPosition().isEmpty()){
            searchCondition.append("，区位：").append(param.getOdaPosition());
        }
        if(!param.getOdaCaseNo().isEmpty()){
            searchCondition.append("，箱号：").append(param.getOdaCaseNo());
        }
        if(!param.getDepName().isEmpty()){
            searchCondition.append("，领料部门：").append(param.getDepName());
        }
        if(!param.getContractNo().isEmpty()){
            searchCondition.append("，合同编号：").append(param.getContractNo());
        }
        if(param.getOdaWhiId() != null && param.getOdaWhiId() != 0){
            TWarehouseInfo warehouseInfo = tWarehouseInfoDao.getTWarehouseInfoByWhiId(param.getOdaWhiId());
            searchCondition.append("，仓库：").append(warehouseInfo.getWhiName());
        }else{
            searchCondition.append("，仓库：").append("全部");
        }
        if(param.getInOutType() != null && param.getInOutType() != 0){
            if(param.getInOutType() == 1){
                searchCondition.append("，出入库类型：").append("入库");
            }
            else if(param.getInOutType() == 2){
                searchCondition.append("，出入库类型：").append("出库");
            }
        }else{
            searchCondition.append("，出入库类型：").append("全部");
        }
        if(param.getBillType() != null && param.getBillType() != 0){
            if(param.getBillType() == 1){
                searchCondition.append("，单据类型：").append("采购入库");
            }
            else if(param.getBillType() == 2){
                searchCondition.append("，单据类型：").append("领料出库");
            }
            else if(param.getBillType() == 3){
                searchCondition.append("，单据类型：").append("串料出库");
            }
            else if(param.getBillType() == 4){
                searchCondition.append("，单据类型：").append("调拨出库");
            }
            else if(param.getBillType() == 5){
                searchCondition.append("，单据类型：").append("车间返料");
            }
            else if(param.getBillType() == 6){
                searchCondition.append("，单据类型：").append("串料剩余");
            }
            else if(param.getBillType() == 7){
                searchCondition.append("，单据类型：").append("项目完结剩余");
            }
            else if(param.getBillType() == 8){
                searchCondition.append("，单据类型：").append("调拨入库");
            }
        }else{
            searchCondition.append("，单据类型：").append("全部");
        }
        if(param.getPStartDate()!=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            searchCondition.append("，制单时间：").append("开始：").append(sdf.format(param.getPStartDate()));
        }
        if(param.getPEndDate()!=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            searchCondition.append("，制单时间：").append("结束：").append(sdf.format(param.getPEndDate()));
        }
        JsonResult jsonResult = new JsonResult();
        if (param.getPEndDate() != null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(param.getPEndDate());
            cal.add(Calendar.DAY_OF_YEAR, 1);
            param.setPEndDate(cal.getTime());
        }
        //获取当前用户
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        //存储/读取Excel的文件夹的路径 mms文件夹下/用户账户/
        String path = uploadPath + user.getAccount() + "/";
        Subject userSubject = ShiroUtils.getSubject();
        String excelFileName = "外购件库出入库综合查询.xlsx";
        try {
            //1.创建临时内存表名
            String tempTableName = "##" + user.getAccount() + (UUID.randomUUID().toString().replace("-", ""));
            param.setTempTableName(tempTableName);
            //2.查询出数据导入到临时表
            if (userSubject.isPermitted("purwar:amount:view")) {
                purWarQueryDao.createWarQueryTempTableByParam(param);
            } else {
                purWarQueryDao.createWarQueryTempTableByParamAndNoAmount(param);
            }
            //3.导出Excel
            if (ExportExcelUtils.BuildExcel(path, excelFileName, tempTableName, active,true)) {
                jsonResult.setData(excelFileName);
                jsonResult.setType(JsonResult.ResultType.SUCCESS);
            } else {
                jsonResult.setType(JsonResult.ResultType.ERROR);
            }
        } catch (Exception e) {
            log.debug(e.getMessage());
            e.printStackTrace();
            jsonResult.setType(JsonResult.ResultType.ERROR);
        }
        // 记录结束时间
        long endTime = System.nanoTime();
        Date endTimeDate = new Date();
        // 计算耗时（秒）
        double elapsedSeconds = (endTime - startTime) / 1_000_000_000.0;
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        logService.saveLog(param.getMode()+"——导出","用户:【"+user.getName()+"】执行导出操作完成，查询条件"+searchCondition+",开始导出时间："+sdf1.format(startTimeDate)+"，返回导出结果时间："+sdf1.format(endTimeDate)+"，总耗时"+elapsedSeconds+"秒！");
        return jsonResult;
    }
}
